/* weehttpd
 * Copyright (c) 2008 Jeffery Myers
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef _WeeHTTPD_H_
#define _WeeHTTPD_H_

#include <string>
#include <vector>
#include <map>

#define _WEE_VERSION "0.01"

typedef enum {
  eUnknown = 0,
  eHead,
  eGet,
  ePost,
  ePut,
  eDelete,
  eTrace,
  eOptions,
  eConnect,
  eOther
}WeeHTTPRequestType;

class WeeHTTPRequest
{
public:
  WeeHTTPRequest() : requestID(-1), request(eUnknown){};

  int		  sessionID;
  int		  requestID;
  WeeHTTPRequestType request;

  std::string vdir;
  std::string resource;
  std::map<std::string, std::vector<std::string> > parameters;

  std::map<std::string, std::string> headers;
  std::map<std::string, std::string> cookies;

  std::string body;
  std::string baseURL;

  //connetion info
  std::string ip;
  std::string hostmask;

  // HTTP auth
  std::string authType;
  std::string authCredentials;

  std::string username;
  std::string password;

  bool getParam(const char* param, std::string &val) const;
  bool getParam(const std::string &param, std::string &val) const;

  bool getParam(const char* param, std::vector<std::string> &val) const;
  bool getParam(const std::string &param, std::vector<std::string> &val) const;

  bool getParam(const char* param) const;
  bool getParam(const std::string &param) const;

};

class WeeHTTPReply
{
public:
  WeeHTTPReply(): docType(eText), returnCode(e404NotFound), forceNoCache(true), bodyData(NULL), bodySize(0) {};
  virtual ~WeeHTTPReply(){if (bodyData)free(bodyData);}

  typedef enum {
    eText,
    eOctetStream,
    eBinary,
    eHTML,
    eCSS,
    eXML,
    eJSON,
    eOther
  } DocumentType;

  typedef enum {
    e200OK,
    e301Redirect,
    e302Found,
    e401Unauthorized,
    e403Forbiden,
    e404NotFound,
    e500ServerError
  } ReturnCode;

  DocumentType docType;
  ReturnCode  returnCode;
  std::string otherMimeType;
  std::map<std::string, std::string> headers;
  std::map<std::string, std::string> cookies;

  std::string body;

  size_t addBody ( const char* data, size_t size );
  size_t getBodySize ( void );
  const char * getBody ( void );

  // authentication method
  std::string authType;
  std::string authRealm;

  bool forceNoCache;

  // content info
  std::string lastUpdateTime;
  std::string md5;

  std::string redirectLoc;

protected:
  char *bodyData;
  size_t bodySize;
};

class WeeHTTPVDir
{
public:
  WeeHTTPVDir();
  virtual ~WeeHTTPVDir();

  typedef enum {
    e404 = 0, // not found
    e200,     // ok
    eDeffer
  } PageStatus;

  virtual const char * getVDir(void){return "*";}
  virtual const char * getDescription(void) { return ""; }
  virtual bool supportPut(void) { return false; }

  virtual bool handleRequest(const WeeHTTPRequest &request, WeeHTTPReply &reply);

  virtual bool resumeTask(int /*requestID*/) {return true; }

protected:
  virtual bool generatePage(const WeeHTTPRequest &/*request*/, WeeHTTPReply &/*reply*/){return true;}
  
  std::string getBaseURL(void);

  void addMimeType ( const std::string &extension, const std::string &type );
  void addMimeType ( const char* extension, const char* type ){addMimeType(std::string(extension),std::string(type));}

  void clearMimeTypes ( void ){mimeTypes.clear();}

  bool serviceMimeResources;
  std::string resourceRootPath;

  std::map<std::string,std::string> mimeTypes;
};

// this network handler class must be implemented for the HTTP instance
class WeeHTTPNetworkHandler
{
public:
  virtual ~WeeHTTPNetworkHandler(){};

  // returns true if there is a new connection
  virtual bool accept ( unsigned int &connectionID ) = 0;

  // returns a string containg the IP address of the connection
  virtual const char* getConnectionIP ( unsigned int &connectionID ) = 0;

  // returns a string containing the hostmask of the connection, if reverse DNS
  // must happen, the command can return NULL at first and return the valid data when the
  // dns lookup is complete.
  virtual const char* getConnectionHost ( unsigned int &connectionID ) = 0;

  // returns the size of the pending data for a connection, if data is not dull the data is COPIED to the buffer and then removed from the
  // network handler and assumed received.
  virtual size_t receive ( unsigned int connectionID, void * data = NULL ) = 0;

  // sends the data from the buffer.
  // returns the size sent.
  // the data must be copied
  // if the returned size is less then the send size, send will be called with the remainder later
  // the network hander MAY buffer this itself if it wishes to
  virtual size_t send ( unsigned int connectionID, const void* data, size_t size ) = 0;

  // returns true if the connection ID can accept another send
  // if the network system is buffering, this can return true all the time
  virtual bool readyForSend ( unsigned int connectionID ) = 0;

  // returns true if the connection ID is still open
  virtual bool isOpen ( unsigned int connectionID ) = 0;

  // forces a connection ID to close itself
  virtual void close ( unsigned int connectionID ) = 0;
};

class WeeHTTPDOptions 
{
public:
  WeeHTTPNetworkHandler *networking;
  std::vector<std::string> hosts;
  std::vector<WeeHTTPVDir*> vdirs;
  bool threadedUpdate;
  bool forceClose;
  std::string serverName;
  std::string serverVersion;
  std::string rootHost;

  WeeHTTPDOptions(WeeHTTPNetworkHandler*n = NULL,const std::string& host = std::string("localhost:80"), WeeHTTPVDir* handler = NULL)
  {
    forceClose = false;
    threadedUpdate = false;
    n = networking;
    hosts.push_back(host);
    if(handler)
      vdirs.push_back(handler);

    serverName = "WeeHTTPServer";
    serverVersion = "WeeHTTPD v:";
    serverVersion += _WEE_VERSION;

    rootHost = "SomeDumbServer";
    if (hosts.size())
      rootHost = hosts[0];
  }
};

// virtual interface for HTTP servers
class WeeHTTPD
{
protected:
  virtual ~WeeHTTPD(){};

public:
  virtual bool registerVDir(WeeHTTPVDir* handler){return false;}
  virtual bool removeVDir(WeeHTTPVDir* handler){return false;}

  virtual void update ( void ){};
};

WeeHTTPD *startHPPT(const WeeHTTPDOptions& options);
bool stopHTTPD(WeeHTTPD* httpd);


#endif //_WeeHTTPD_H_


// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
